package com.study.example.gameserver.module.ranklist.manager;

import com.sparrow.cache.entity.EntityCache;
import com.sparrow.common.handler.HandlerManager;
import com.sparrow.common.ranklist.RankList;
import com.sparrow.common.value.EnumUtil;
import com.sparrow.event.annotation.EventReceiver;
import com.study.example.gameserver.event.ServerInitEvent;
import com.study.example.gameserver.module.ranklist.domain.RankType;
import com.study.example.gameserver.module.ranklist.entity.PlayerRank;
import com.study.example.gameserver.module.ranklist.entity.PlayerRankId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class RankManager {

    private ConcurrentHashMap<RankType, RankList> rankListMap = new ConcurrentHashMap<>();

    private ConcurrentHashMap<RankType, Map<Long, PlayerRank>> rankMap = new ConcurrentHashMap<>();

    @Autowired
    private EntityCache<PlayerRankId, PlayerRank> entityCache;

    @Autowired
    private HandlerManager handlerManager;

    private static final int RANK_CAPACITY = 100;
    @EventReceiver
    public void init(ServerInitEvent initEvent) {
        Map<Integer, List<PlayerRank>> typeDataMap = new HashMap<>();
        List<PlayerRank> all = entityCache.list();
        for (PlayerRank playerRank : all) {
            List<PlayerRank> playerRanks = typeDataMap.computeIfAbsent(playerRank.getRankType(), k -> new ArrayList<>());
            playerRanks.add(playerRank);
        }

        for (Map.Entry<Integer, List<PlayerRank>> e : typeDataMap.entrySet()) {
            RankType rankType = EnumUtil.valueOf(RankType.class, e.getKey());
            RankList rankList = new RankList(RANK_CAPACITY);
            rankList.resort(e.getValue());

            rankListMap.put(rankType, rankList);
        }
    }

    public PlayerRank getOrCreateRank(RankType rankType, long playerId) {
        Map<Long, PlayerRank> map = rankMap.computeIfAbsent(rankType, k -> new ConcurrentHashMap<>());
        return map.computeIfAbsent(playerId, k -> {
            PlayerRank playerRank = entityCache.getOrCreate(new PlayerRankId(playerId, rankType.getType()), e -> {
                e.setPlayerId(k);
                e.setRankType(rankType.getType());
            });
            return playerRank;
        });
    }

    public void updateRank(RankType rankType, PlayerRank playerRank) {
        RankList rankList = getRankList(rankType);
        rankList.update(playerRank);
    }

    public RankList getRankList(RankType rankType) {
        return rankListMap.computeIfAbsent(rankType, k -> new RankList(RANK_CAPACITY));
    }
}
